import { useState, useRef, useEffect } from 'react'
import { Toast } from '@/hooks/use-toast'
import { Card } from '@/components/ui/card'
import { Play, Pause, Volume2, VolumeX, Download } from 'lucide-react'
import { uploadService } from '@/services'
import { downloadFile } from '@/lib/download'
import { Language } from '@/lib/i18n'
import { CustomDialog } from '@/components/CustomDialog'
import { commonService } from '@/services'
import styles from './VideoLipSync.module.scss'
import AudioSettings from '../AudioSettings'
import { cn } from '@/lib/utils'
import { Button, Input } from '@/components/ui'

interface UploadState {
  videoFile: File | null
  audioFile: File | null
  videoUrl: string
  audioUrl: string
  isUploading: boolean
  isProcessing: boolean
  resultUrl: string
  uploadProgress: number
  videoPreviewUrl: string
  audioPreviewUrl: string
  taskId: string | null
}

interface VideoLipSyncProps {
  lang: Language
}

const VideoLipSync = ({ lang }: VideoLipSyncProps) => {
  const [state, setState] = useState<UploadState>({
    videoFile: null,
    audioFile: null,
    videoUrl: '',
    audioUrl: '',
    isUploading: false,
    isProcessing: false,
    resultUrl: '',
    uploadProgress: 0,
    videoPreviewUrl: '',
    audioPreviewUrl: '',
    taskId: null,
  })

  const [isVideoPlaying, setIsVideoPlaying] = useState<boolean>(false)
  const [isAudioPlaying, setIsAudioPlaying] = useState<boolean>(false)
  const [isMuted, setIsMuted] = useState<boolean>(false)
  const [isResultPlaying, setIsResultPlaying] = useState<boolean>(false)
  const [isResultMuted, setIsResultMuted] = useState<boolean>(false)

  const videoRef = useRef<HTMLVideoElement>(null)
  const audioRef = useRef<HTMLAudioElement>(null)
  const resultVideoRef = useRef<HTMLVideoElement>(null)

  // 添加新的状态
  const [showTTSModal, setShowTTSModal] = useState<boolean>(false)

  useEffect(() => {
    let pollInterval: NodeJS.Timeout | null = null

    const checkTaskStatus = async (): Promise<void> => {
      if (!state.taskId || !state.isProcessing) return

      try {
        const data = await commonService.getLipSyncTaskDetail(state.taskId)
        console.log('Task status:', data)

        if (data.status === 'COMPLETED' && data.result?.outputUrl) {
          setState((prev) => ({
            ...prev,
            isProcessing: false,
            resultUrl: data.result.outputUrl || '',
          }))

          Toast.show({
            content: 'Video generation completed!',
            icon: 'success',
          })

          if (pollInterval) clearInterval(pollInterval)
        } else if (data.status === 'FAILED') {
          setState((prev) => ({
            ...prev,
            isProcessing: false,
          }))

          Toast.show({
            content: data.error_message || 'Video generation failed',
            icon: 'error',
          })

          if (pollInterval) clearInterval(pollInterval)
        }
      } catch (error) {
        console.error('Error checking status:', error)
      }
    }

    if (state.taskId && state.isProcessing) {
      pollInterval = setInterval(checkTaskStatus, 5000)
    }

    return () => {
      if (pollInterval) clearInterval(pollInterval)
    }
  }, [state.taskId, state.isProcessing])

  const uploadFile = async (
    file: File,
    type: 'video' | 'audio',
  ): Promise<string> => {
    try {
      console.log(`Starting upload for ${type}:`, file.name)

      const result = await uploadService.uploadFile(file, (progress) => {
        console.log(`Upload progress: ${progress}%`)
        setState((prev) => ({
          ...prev,
          uploadProgress: progress,
        }))
      })

      console.log(`${type} upload completed:`, result.url)
      return result.url
    } catch (error) {
      console.error(`Upload error for ${type}:`, error)
      throw error
    }
  }

  const handleFileChange = (
    event: React.ChangeEvent<HTMLInputElement>,
    type: 'video' | 'audio',
  ): void => {
    const file = event.target.files?.[0]
    if (file) {
      console.log(`Selected ${type} file:`, file.name, 'size:', file.size)

      const previewUrl = URL.createObjectURL(file)

      setState((prev) => ({
        ...prev,
        [`${type}File`]: file,
        [`${type}PreviewUrl`]: previewUrl,
        uploadProgress: 0,
      }))

      if (type === 'video' && videoRef.current) {
        videoRef.current.pause()
        setIsVideoPlaying(false)
      } else if (type === 'audio' && audioRef.current) {
        audioRef.current.pause()
        setIsAudioPlaying(false)
      }
    }
  }

  const handleVideoPlayPause = (): void => {
    if (videoRef.current) {
      if (isVideoPlaying) {
        videoRef.current.pause()
      } else {
        videoRef.current.play()
      }
      setIsVideoPlaying(!isVideoPlaying)
    }
  }

  const handleAudioPlayPause = (): void => {
    if (audioRef.current) {
      if (isAudioPlaying) {
        audioRef.current.pause()
      } else {
        audioRef.current.play()
      }
      setIsAudioPlaying(!isAudioPlaying)
    }
  }

  const handleVideoEnded = (): void => {
    setIsVideoPlaying(false)
  }

  const handleAudioEnded = (): void => {
    setIsAudioPlaying(false)
  }

  const handleToggleMute = (): void => {
    if (videoRef.current) {
      videoRef.current.muted = !isMuted
      setIsMuted(!isMuted)
    }
  }

  const handleResultPlayPause = (): void => {
    if (resultVideoRef.current) {
      if (isResultPlaying) {
        resultVideoRef.current.pause()
      } else {
        resultVideoRef.current.play()
      }
      setIsResultPlaying(!isResultPlaying)
    }
  }

  const handleResultEnded = (): void => {
    setIsResultPlaying(false)
  }

  const handleResultToggleMute = (): void => {
    if (resultVideoRef.current) {
      resultVideoRef.current.muted = !isResultMuted
      setIsResultMuted(!isResultMuted)
    }
  }

  const handleDownload = async (): Promise<void> => {
    if (!state.resultUrl) return

    try {
      Toast.show({
        content: 'Preparing download...',
        icon: 'loading',
        duration: Infinity,
      })
      await downloadFile(state.resultUrl)
      Toast.clear()
      Toast.show({
        content: 'Download completed!',
        icon: 'success',
      })
      return
    } catch (error) {
      console.error('Download error:', error)
      Toast.clear()
      Toast.show({
        content:
          error instanceof Error
            ? error.message
            : 'Download failed, please try again',
        icon: 'error',
        duration: 2000,
      })
    }
  }

  const generateVideo = async (): Promise<void> => {
    if (!state.videoFile || !state.audioFile) {
      Toast.show({
        content: 'Please upload video and audio files first',
        icon: 'error',
      })
      return
    }

    setState((prev) => ({ ...prev, isUploading: true }))

    try {
      console.log('Starting file uploads...')
      const [videoUrl, audioUrl] = await Promise.all([
        uploadFile(state.videoFile, 'video'),
        uploadFile(state.audioFile, 'audio'),
      ])

      // 调用 commonService 创建口型任务
      const taskData = await commonService.createLipSyncTask(videoUrl, audioUrl)
      console.log('taskData', taskData)

      if (!taskData) {
        throw new Error('Failed to start video processing')
      }

      const taskId = taskData.no

      setState((prev) => ({
        ...prev,
        taskId,
        isUploading: false,
        isProcessing: true,
      }))

      Toast.show({
        content: 'Processing video, please wait...',
        icon: 'success',
      })
    } catch (error) {
      console.error('Error:', error)
      Toast.show({
        content:
          error instanceof Error
            ? error.message
            : 'Processing failed, please try again',
        icon: 'error',
      })
      setState((prev) => ({
        ...prev,
        isUploading: false,
        isProcessing: false,
      }))
    }
  }

  return (
    <div className="flex h-full flex-1 gap-x-6 pt-1 px-4 pb-6 gap-4">
      <div className="flex flex-col w-[336px] gap-2.5 h-full">
        <div className="flex-1 flex flex-col gap-4 my-scrollbar overflow-hidden overflow-y-auto">
          <div className="flex flex-col">
            <div className="border border-[#B9AEFF]/10 rounded-[14px] p-4 bg-white/10">
              <div className="text-sm text-white/80 font-medium font-ak mb-2.5">
                Audio and video synthesis
              </div>
              <p className="text-sm text-white/60 font-normal font-ak capitalize pb-5">
                Please use the front face as much as possible, and play the video in
                a loop without being obtrusive. The length of the generated video
                should be the same as the input audio length, and has nothing to do
                with the length of the video.
              </p>
              <div className="text-sm text-white/80 font-medium font-ak mb-2.5">
                Original Video
              </div>
              <div className="relative rounded-[10px] h-[38px] bg-black/40">
                <label
                  htmlFor="videoInput"
                  className="absolute p-2.5 left-0 top-0 w-full h-full flex items-center justify-center cursor-pointer"
                >
                  <span
                    className={cn(
                      'text-sm text-[#A091FD] font-ak font-normal overflow-hidden text-ellipsis',
                      state.videoFile?.name && 'text-white',
                    )}
                  >
                    {state.videoFile?.name || 'Select file'}
                  </span>
                </label>
                <Input
                  id="videoInput"
                  type="file"
                  accept="video/*"
                  onChange={(e) => handleFileChange(e, 'video')}
                  disabled={state.isUploading || state.isProcessing}
                  className="hidden"
                />
              </div>
              {state.videoFile && (
                <div className="flex flex-col">
                  <div className="pb-2.5 pt-5 text-sm text-white/60 font-ak font-normal text-ellipsis overflow-hidden">
                    {state.isUploading && state.uploadProgress > 0 ? (
                      <span>Upload Progress: {state.uploadProgress}%</span>
                    ) : (
                      <span>{state.videoFile.name}</span>
                    )}
                  </div>
                  <div className="w-full h-52 relative">
                    <video
                      ref={videoRef}
                      src={state.videoPreviewUrl}
                      className="w-full h-full object-cover rounded-[10px]"
                      onEnded={handleVideoEnded}
                      controls
                    />
                    {/* <div className="absolute bottom-0 left-0 right-0">
                        <Button
                          variant="ghost"
                          size="icon"
                          onClick={handleVideoPlayPause}
                        >
                          {isVideoPlaying ? <Pause size={20} /> : <Play size={20} />}
                        </Button>
                        <Button
                          variant="ghost"
                          size="icon"
                          onClick={handleToggleMute}
                        >
                          {isMuted ? <VolumeX size={20} /> : <Volume2 size={20} />}
                        </Button>
                      </div> */}
                  </div>
                </div>
              )}
            </div>
          </div>
          <div className="flex flex-col">
            <div className="border border-[#B9AEFF]/10 rounded-[14px] p-4 bg-white/10">
              <div className="text-sm text-white/80 font-medium font-ak mb-2.5">
                Target Audio
              </div>
              <div className="flex flex-row gap-2.5">
                <div className="relative flex-1 rounded-[10px] h-[38px] bg-black/40">
                  <label
                    htmlFor="audioInput"
                    className="absolute p-2.5 left-0 top-0 w-full h-full flex items-center justify-center cursor-pointer"
                  >
                    <span
                      className={cn(
                        'text-sm text-[#A091FD] font-ak font-normal overflow-hidden text-ellipsis',
                        state.audioFile?.name && 'text-white',
                      )}
                    >
                      {state.audioFile?.name || 'Select file'}
                    </span>
                  </label>
                  <input
                    id="audioInput"
                    type="file"
                    accept="audio/*"
                    onChange={(e) => handleFileChange(e, 'audio')}
                    className="hidden"
                  />
                </div>
                <div
                  className="rounded-[10px] h-[38px] w-28 bg-black/40 flex items-center justify-center text-[#A091FD] cursor-pointer"
                  onClick={() => setShowTTSModal(true)}
                >
                  Text to Audio
                </div>
              </div>
              {state.audioFile && (
                <div className="flex flex-col">
                  <div className="pb-2.5 pt-5 text-sm text-white/60 font-ak font-normal text-ellipsis overflow-hidden">
                    <span>{state.audioFile.name}</span>
                  </div>
                  <div className="w-full h-9 relative">
                    <audio
                      ref={audioRef}
                      src={state.audioPreviewUrl}
                      className="w-full h-full rounded-[10px]"
                      onEnded={handleAudioEnded}
                      controls
                    />
                    {/* <div className="absolute bottom-0 left-0 right-0">
                        <Button
                          variant="ghost"
                          size="icon"
                          onClick={handleAudioPlayPause}
                        >
                          {isAudioPlaying ? <Pause size={20} /> : <Play size={20} />}
                        </Button>
                      </div> */}
                  </div>
                </div>
              )}
            </div>
          </div>
        </div>
        <div className="flex items-center px-6">
          <Button
            onClick={generateVideo}
            disabled={
              !state.videoFile ||
              !state.audioFile ||
              state.isUploading ||
              state.isProcessing
            }
            className="h-11 w-full rounded-full disabled:bg-[#B9AEFF]/10 disabled:text-white/80"
          >
            {state.isUploading
              ? `Uploading ${state.uploadProgress}%`
              : state.isProcessing
                ? 'Processing...'
                : 'Generate Video'}
          </Button>
        </div>
      </div>
      <div className="flex flex-1 flex-col border border-[#B9AEFF]/10 rounded-[14px] p-4 bg-white/10">
        <div className="text-white/80 text-sm">Generate results</div>
        <div className="flex items-center justify-center flex-1 p-4">
          {state.resultUrl && (
            <video
              src={state.resultUrl}
              className="w-full h-full max-w-[284px] max-h-[490px] object-cover rounded-[10px]"
              controls
            />
          )}
        </div>
      </div>
      <CustomDialog
        className="max-w-md"
        title="Audio Generation"
        open={showTTSModal}
        onOpenChange={setShowTTSModal}
      >
        <AudioSettings
          isCreateAudio={true}
          confirm={async (options) => {
            // 创建一个新的 File 对象
            const audioResponse = await fetch(options.url!)
            const audioBlob = await audioResponse.blob()
            const audioFile = new File([audioBlob], `tts_${Date.now()}.mp3`, {
              type: 'audio/mp3',
            })

            // 更新状态
            const audioPreviewUrl = URL.createObjectURL(audioBlob)
            setState((prev) => ({
              ...prev,
              audioFile,
              audioPreviewUrl,
            }))
          }}
          cancelClick={() => {
            console.log('cancel')
            setShowTTSModal(false)
          }}
        ></AudioSettings>
      </CustomDialog>
    </div>
  )
}

export default VideoLipSync
